﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace klg_client.library
{
    public class KeyEntry
    {
        public Keys VirtualKey { get; set; }

        public char Char { get; set; }

        public char CharShift { get; set; }

        public char CharAlt { get; set; }

        public char CharControl { get; set; }
    }

    public class KeyboardLayout
    {
        private static KeyboardLayout _instance;

        public static KeyboardLayout Instance
        {
            get { return _instance ?? (_instance = new KeyboardLayout()); }
        }

        readonly List<KeyEntry> _data; 

        public KeyboardLayout()
        {
            _data = new List<KeyEntry>();
            var hkl = InputLanguage.CurrentInputLanguage.Handle;

            uint[] rgScOfVk = new uint[256];
            for (uint sc = 0x01; sc <= 0x7f; sc++)
            {
                uint vk = WinApi.MapVirtualKeyEx(sc, 3, hkl);
                if (vk != 0)
                {
                    rgScOfVk[vk] = sc;
                }
            }

            byte[] lpKeyState = new byte[256];
            for (uint vk = 0x01; vk < rgScOfVk.Length; vk++)
            {
                if (rgScOfVk[vk] != 0)
                {
                    var key = (Keys)vk;
                    StringBuilder sb = new StringBuilder(10);
                    char ch = (char)0;
                    int rc = WinApi.ToUnicodeEx(vk, rgScOfVk[vk], lpKeyState, sb, sb.Capacity, 0, hkl);
                    if (rc > 0)
                    {
                        ch = sb[0];
                    }
                    else if (rc < 0)
                    {
                        ch = sb[0];
                        WinApi.ToUnicodeEx((uint)Keys.Space, rgScOfVk[(uint)Keys.Space], lpKeyState, sb, sb.Capacity, 0, hkl);
                    }

                    if (ch > 0)
                    {
                        var entry = new KeyEntry { VirtualKey = key, Char = ch };
                        _data.Add(entry);
                    }
                }
            }


            //for (uint sc = 0x01; sc <= 0x7f; sc++)
            //{
            //    uint vk = WinApi.MapVirtualKeyEx(sc, 3, hkl);
            //    if (vk != 0)
            //    {
            //        var key = (Keys)vk;
            //        StringBuilder sb = new StringBuilder(10);
            //        char ch = (char) 0;
            //        int rc = WinApi.ToUnicodeEx(vk, sc, lpKeyState, sb, sb.Capacity, 0, hkl);
            //        if (rc > 0)
            //        {
            //            ch = sb[0];
            //        }
            //        else if (rc < 0)
            //        {
            //            ch = sb[0];
            //            uint scan = WinApi.MapVirtualKeyEx((uint)Keys.Space, 0, hkl);
            //            WinApi.ToUnicodeEx((uint)Keys.Space, scan, lpKeyState, sb, sb.Capacity, 0, hkl);
            //        }

            //        if (ch > 0)
            //        {
            //            var entry = new KeyEntry { VirtualKey = key, Char = ch };
            //            _data.Add(entry);
            //        }
            //    }
            //}
        }

        public List<KeyEntry> GetMap()
        {
            return _data;
        }

        public char GetCharFromVirtualKey(Keys key, bool shift = false, bool alt = false, bool control = false)
        {
            var entry = _data.Find(x => x.VirtualKey == key);
            if (entry != null)
            {
                if (shift)
                    return entry.CharShift;

                if (alt)
                    return entry.CharAlt;

                if (control)
                    return entry.CharControl;

                return entry.Char;
            }
            return (char) 0;
        }
    }
}
